#include <stdlib.h>
#include <stdio.h>
#include <GL/freeglut.h>

#include "utility.h"

int g_sw = 800;
int g_sh = 600;
double g_angleX = 0.0;
double g_angleY = 0.0;
double g_angleZ = 0.0;
int g_stateLeft = GLUT_UP;
int g_stateMiddle = GLUT_UP;
int g_stateRight = GLUT_UP;
int g_preX = 0;
int g_preY = 0;

bool g_splitWindow = false;

void Update()
{
//	g_angleX += 0.12f;
}

void PaintAllAxis()
{
	glColor3f(1.0, 0.0, 0.0);
	drawLine(0.0, 0.0, 0.0, 3.0, 0.0, 0.0);
	glColor3f(0.0, 1.0, 0.0);
	drawLine(0.0, 0.0, 0.0, 0.0, 3.0, 0.0);
	glColor3f(1.0, 1.0, 0.0);
	drawLine(0.0, 0.0, 0.0, 0.0, 0.0, 3.0);
}

void PaintStuff()
{
	glutWireTeapot(2.0);
}

void PaintFrame()
{
	glClear(GL_COLOR_BUFFER_BIT);

	if(g_splitWindow)
	{
		glViewport(0, 0, g_sw, g_sh);
		glColor3f(1.0, 1.0, 1.0);
		glLoadIdentity();
		gluLookAt(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
		drawLine(0.0, -1.0, 0.0, 0.0, 1.0, 0.0);
		drawLine(100.0, 0.0, 0.0, -100.0, 0.0, 0.0);

		glViewport(0, g_sh/2, g_sw/2, g_sh/2);
		glColor3f(1.0, 1.0, 1.0);
		glLoadIdentity();
		gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
		glScalef(1.0, 1.0, 1.0);
		glRotatef(g_angleX, 1.0, 0.0, 0.0);
		glRotatef(g_angleY, 0.0, 1.0, 0.0);
		glRotatef(g_angleZ, 0.0, 0.0, 1.0);
		PaintStuff();
		PaintAllAxis();
		
		glViewport(g_sw/2, g_sh/2, g_sw/2, g_sh/2);
		glColor3f(1.0, 0.0, 1.0);
		glLoadIdentity();
		gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
		glScalef(1.0, 1.0, 1.0);
		PaintStuff();
		PaintAllAxis();
		
		glViewport(0, 0, g_sw/2, g_sh/2);
		glColor3f(1.0, 1.0, 0.0);
		glLoadIdentity();
		gluLookAt(0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);
		glScalef(1.0, 1.0, 1.0);
		PaintStuff();
		PaintAllAxis();

		glViewport(g_sw/2, 0, g_sw/2, g_sh/2);
		glColor3f(0.0, 1.0, 1.0);
		glLoadIdentity();
		gluLookAt(5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
		glScalef(1.0, 1.0, 1.0);
		PaintStuff();
		PaintAllAxis();
	}
	else
	{
		glViewport(0, 0, g_sw, g_sh);
		glColor3f(1.0, 1.0, 1.0);
		glLoadIdentity();
		gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
		glScalef(1.0, 1.0, 1.0);
		glRotatef(g_angleZ, 0.0, 0.0, 1.0);
		glRotatef(g_angleX, 1.0, 0.0, 0.0);
		glRotatef(g_angleY, 0.0, 1.0, 0.0);
		PaintStuff();
		PaintAllAxis();
	}

	glutSwapBuffers();
//	glFlush();
}

void OnDisplay()
{
	Update();

	PaintFrame();
}

void OnReshape(int w, int h)
{
	g_sw = w; 
	g_sh = h;
	glClear(GL_COLOR_BUFFER_BIT);
	
	glViewport(0, g_sh/2, g_sw/2, g_sh);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, g_sw/(double)g_sh, 1.5, 200);
	glMatrixMode(GL_MODELVIEW);
	glViewport(g_sw/2, g_sh/2, g_sw, g_sh);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, g_sw/(double)g_sh, 1.5, 200);
	glMatrixMode(GL_MODELVIEW);
	glViewport(0, 0, g_sw/2, g_sh/2);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, g_sw/(double)g_sh, 1.5, 200);
	glMatrixMode(GL_MODELVIEW);
	glViewport(g_sw/2, 0, g_sw, g_sh/2);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, g_sw/(double)g_sh, 1.5, 200);
	glMatrixMode(GL_MODELVIEW);
	
	glViewport(0, 0, g_sw, g_sh);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, g_sw/(double)g_sh, 0.5, 200);
	glMatrixMode(GL_MODELVIEW);
}

void OnTimer(int value)
{
	if(value == 0)
	{
		glutPostRedisplay();
		glutTimerFunc(20, OnTimer, 0);
	}
}

void OnKeyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
		case 's':
			g_splitWindow = !g_splitWindow;
		break;
	}
}

void OnMouse(int button, int state, int x, int y)
{
	if(GLUT_LEFT_BUTTON == button)
	{
		g_stateLeft = state;
	}
	else if(GLUT_RIGHT_BUTTON == button)
	{
		g_stateRight = state;
	}
	else if(GLUT_MIDDLE_BUTTON == button)
	{
		g_stateMiddle = state;
	}
	g_preX = x;
	g_preY = y;
	
//	printf("PRE(%d, %d), NOW(%d, %d)\n", g_preX, g_preY, x, y);
}

void OnMotion(int x, int y)
{
	double divX, divY;
	divX = x - g_preX;
	divY = y - g_preY;

	if(GLUT_DOWN == g_stateLeft)
	{
		g_angleX += divX/2.0;
	}
	if(GLUT_DOWN == g_stateRight)
	{
		g_angleY += divX/2.0;
	}
	if(GLUT_DOWN == g_stateMiddle)
	{
		g_angleZ += divX/2.0;
	}
	g_preX = x;
	g_preY = y;
}

void init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_FLAT);
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(g_sw, g_sh);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("hello");
	init();
	glutDisplayFunc(OnDisplay);
	glutReshapeFunc(OnReshape);
	glutKeyboardFunc(OnKeyboard);
	glutMouseFunc(OnMouse);
	glutMotionFunc(OnMotion);
	glutTimerFunc(20, OnTimer, 0);
	glutMainLoop();
	return 0;
}
